package org.absolutezero.model;

import java.io.Serializable;
import java.util.List;
import java.util.logging.Logger;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.persistence.Version;

import org.absolutezero.shared.ShelfProxy;




@Entity
@Table(name = "shelf")
public class Shelf implements Serializable
{
	    private static Logger logger = Logger.getLogger(User.class.getName());
	
	    @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;

	    @Version
	    private Integer version;
	    
        
        @ManyToOne(fetch=FetchType.EAGER)
        @JoinColumn(name="owner_id")
        private User owner;
        
        @OneToMany(mappedBy = "shelf",cascade={CascadeType.ALL},fetch=FetchType.EAGER)
        private List<FridgeProduct> fridgeProducts;

        public List<FridgeProduct> getFridgeProducts() {
			return fridgeProducts;
		}


		public void setFridgeProducts(List<FridgeProduct> fridgeProducts) {
			this.fridgeProducts = fridgeProducts;
		}

		private String name;
        
        private Boolean publicRead;
        
        private Boolean publicWrite;
        
        public Long getId() {
			return id;
		}


		public void setId(Long id) {
			this.id = id;
		}


		public User getOwner(){
			return owner;
		}
		
		public void setOwner(User owner){
			this.owner = owner;
		}


		public String getName() {
			return name;
		}


		public void setName(String name) {
			this.name = name;
		}


		public Boolean getPublicRead() {
			return publicRead;
		}


		public void setPublicRead(Boolean publicRead) {
			this.publicRead = publicRead;
		}


		public Boolean getPublicWrite() {
			return publicWrite;
		}


		public void setPublicWrite(Boolean publicWrite) {
			this.publicWrite = publicWrite;
		}


		public Shelf(){}

        private static EntityManager entityManager(){
        	return EMF.get().createEntityManager();
        }
                        
        
        public void persist() {
        	
    	    EntityManager em = entityManager();
    	    
    	    try {
    	    	
    	      EntityTransaction tx  = em.getTransaction();
     	      tx.begin();
     	      this.owner = em.merge(this.owner);
     	     
    	      Shelf s = em.merge(this);
    	      
    	      for(FridgeProduct p : this.fridgeProducts){
    	    	  p = em.merge(p);
    	    	  p.setShelf(s);
    	      }
    	      
    	      tx.commit();
    	     
    	    } catch(Exception e){
    	    	logger.info(e.getMessage());
    	    }
    	    
    	    
    	    finally {
    	      em.close();
    	    }
    	  }

    	public void remove() {
    	    EntityManager em = entityManager();
    	    try {
    	      Shelf attached = em.find(Shelf.class, this.id);
    	      EntityTransaction tx  = em.getTransaction();
     	      tx.begin();
    	      em.remove(attached);
    	      tx.commit();
    	    } finally {
    	      em.close();
    	    }
    	  }
    	
    	public static Shelf findShelf(Long id){
     		if (id == null) {
     		      return null;
    	    }
    	    EntityManager em = entityManager();
    	    try {
    	      Shelf shelf = em.find(Shelf.class, id);
    	      return shelf;
    	    } finally {
    	      em.close();
    	    }
     	}
    	
    	public static void removeShelfProducts(List<FridgeProduct> products){
    		EntityManager em = entityManager();
    		
    		try{
    			EntityTransaction tx = em.getTransaction();
	    		tx.begin();
	    		for(FridgeProduct p : products){
	    			Query q = em.createQuery(
	    					"DELETE FROM FridgeProduct p WHERE id = :id");
	    			q.setParameter("id", p.getId());
	    			q.executeUpdate();
	    		}
	    		tx.commit();
    		}
    		finally{
    			em.close();
    		}
    	}
    	
    	public static List<Shelf> getAllShelves(){
    		EntityManager em = entityManager();
    		
    		Query q = em.createQuery("SELECT shelf FROM Shelf shelf ");
    		
    		return (List<Shelf>)q.getResultList();
    	}
    	
    	public Integer getVersion(){
     		return version;
     	}
    	
    	public void setVersion(Integer version){
    		this.version = version;
    	}
    	
    	@Override
     	public String toString(){
     		return String.format("User[%d, %d, %s, %b %b]", id, owner.getId(), name, publicRead, publicWrite);
     	}
    	
    	@Override
    	public boolean equals(Object o){
    		if (!(o instanceof Shelf)){
    			return false;
    		}
    		else{
    			Shelf s = (Shelf)o;
    			return this.id == s.id ? true : false;
    		}
    	}

}